import GraphBase from "./graphBase";
import { Point } from "./dependencies";
export default class PolyLineNodeGraph extends GraphBase {
  points: Point[] = [];
  borderColor = "rgb(64,158,255)";
  lineWidth = 1;
  isClose = false;
  type = "polyline";
  originPoints: Point[] = [];
  constructor() {
    super();
  }
  contain(x: number, y: number): boolean {
    for (let i = 0; i < this.points.length - 1; i++) {
      const p1 = this.points[i];
      const p2 = this.points[i + 1];
      // 折线有多条直线,只要在其中一条直线上,就是在这条折线上
      if (this.containLine(p1.x, p1.y, p2.x, p2.y, x, y)) {
        return true;
      }
    }
    return false;
  }
  // 判断是否在一条直线上
  containLine(
    x0: number,
    y0: number,
    x1: number,
    y1: number,
    x: number,
    y: number
  ): boolean {
    if (this.lineWidth === 0) {
      return false;
    }
    const _l = this.lineWidth;
    let _a = 0;
    let _b = x0;
    if (
      (y > y0 + _l && y > y1 + _l) ||
      (y < y0 - _l && y < y1 - _l) ||
      (x > x0 + _l && x > x1 + _l) ||
      (x < x0 - _l && x < x1 - _l)
    ) {
      return false;
    }

    if (x0 !== x1) {
      _a = (y0 - y1) / (x0 - x1);
      _b = (x0 * y1 - x1 * y0) / (x0 - x1);
    } else {
      return Math.abs(x - x0) <= _l / 2;
    }
    const tmp = _a * x - y + _b;
    const _s = (tmp * tmp) / (_a * _a + 1);
    return _s <= _l * _l;
  }
  // 获取折线的外层包围框
  getRect(): {
    x: number;
    y: number;
    width: number;
    height: number;
  } {
    const rect = { x: 0, y: 0, width: 0, height: 0 };
    const firstPoint = this.points[0];
    let minX = firstPoint.x;
    let minY = firstPoint.y;
    let maxX = firstPoint.x;
    let maxY = firstPoint.y;
    for (let i = 1; i < this.points.length; i++) {
      const point = this.points[i];
      if (point.x < minX) {
        minX = point.x;
      }
      if (point.y < minY) {
        minY = point.y;
      }
      if (point.x > maxX) {
        maxX = point.x;
      }
      if (point.y > maxY) {
        maxY = point.y;
      }
    }
    rect.x = minX;
    rect.y = minY;
    rect.width = maxX - minX;
    rect.height = maxY - minY;
    return rect;
  }
  saveOriginPoints() {
    this.originPoints = this.points.map((point) => {
      return new Point(point.x, point.y);
    });
  }
  getOriginPoints(): Point[] {
    return this.originPoints;
  }
  translate(x: number, y: number) {
    const originPoints = this.getOriginPoints();
    this.points = originPoints.map((point) => {
      return new Point(point.x + x, point.y + y);
    });
  }
  offset(x: number, y: number) {}
  draw() {
    if (!this.ctx) {
      return;
    }
    if (this.points.length === 0) {
      return;
    }
    const startPoint = this.points[0];
    this.ctx.strokeStyle = this.borderColor;
    this.ctx.lineWidth = this.lineWidth;
    this.ctx.beginPath();
    this.ctx.moveTo(startPoint.x, startPoint.y);
    for (let i = 1; i < this.points.length; i++) {
      const point = this.points[i];
      this.ctx.lineTo(point.x, point.y);
    }
    if (this.isClose) {
      this.ctx.closePath();
    }
    this.ctx.stroke();
  }
  changeProperty(propertyName: string, propertyValue: any) {
    switch (propertyName) {
      case "borderColor":
        this[propertyName] = propertyValue;
        break;
      case "lineWidth":
        this[propertyName] = propertyValue;
        break;
      case "isClose":
        this[propertyName] = propertyValue;
        break;
      default:
        break;
    }
  }
  setZoom(zoom: number = 1) {
    this.zoom = zoom;
    this.points.forEach((p: Point) => {
      p.setX(p.x * zoom);
      p.setY(p.y * zoom);
    });
  }
  getZoom(): number {
    return this.zoom;
  }
}
